import {
  Directive, ElementRef, HostListener, Inject, Input, Renderer, ViewChild, AfterContentInit,
  Output, EventEmitter, OnDestroy, OnChanges, AfterViewInit
} from '@angular/core';
import {Observable} from "rxjs";
import {ImageServeService} from "../service/image/image-serve.service";
import {DOCUMENT} from '@angular/platform-browser';
import {ToolsService} from "@shared/service/tools/tools.service";
import {EventsService} from "@core/events/events.service";


/**
 * @desc 此指令用于元素监听页面高度小于初始值时候隐藏
 * @author 欧晓辉
 * @class ResizeDisplay
 */
@Directive({
  selector: '[seed-resize-display]'
})
export class ResizeDisplayDirective {
  public height: number;

  constructor(
    private ele: ElementRef,
    private renderer: Renderer,
    @Inject(DOCUMENT) private document
  ) {
    this.height = this.document.documentElement.clientHeight;
  }

  @HostListener('window:resize', ['$event'])
  resize(event) {
    if (window.location.href.indexOf('popup=') !== -1) {
      return;
    }
    let h = this.height;
    if (event.target.innerHeight < Number(h)) {
      this.renderer.setElementStyle(this.ele.nativeElement, 'display', 'none');
    } else {
      this.renderer.setElementStyle(this.ele.nativeElement, 'display', 'block');
    }
  }

}

/**
 * @description 横向滑动
 * @author @chenwh576
 */
@Directive({
  selector: '[seed-roller]'
})
export class RollerDirective implements AfterViewInit {

  @Input('seed-roller') render: boolean;

  constructor(public el: ElementRef) {}

  ngAfterViewInit() {
    /*if (this.render === true) {*/
    if (this.render) {
      this.setScroll();
    }
  }

  public setScroll() {
    let widths = 0;
    let parent = this.el.nativeElement.parentNode;
    const length = parent.children.length;
    for (let i = 0; i < length; i++) {
      widths += parent.children[i].offsetWidth;
    }
    parent.style.width = widths + 'px';
  }
}

/**
 *@description 用于图片加载不出来加载默认展位图时
 * @author @chenwh576
 * 使用方式：
 * <img
 *  seed-load-img
 *  [src]="personHeaderInfo?.iconUrl"
 *  class="person-img"
 *  ngIf="personHeaderInfo?.iconUrl"
 * >
 */
@Directive({
  selector: '[seed-load-img]'
})
export class LoadImgDirective implements AfterContentInit {
  public _defaultImg: string;
  public arr: Object;
  public element: ElementRef;

  @Input() src: string;

  @Input()
  set defaultImg(sub: string) {
    this._defaultImg = this.arr[sub];
  }

  get defaultImg() {
    return this._defaultImg;
  }

  constructor(
    public ele: ElementRef,
    private imgService: ImageServeService
  ) {
    this.arr = {
      avatar: imgService.getAvatarIcon(),
      small: imgService.getSmallArticleImgHolder(),
      middle: imgService.getMiddleArticleImgHolder(),
      long: imgService.getLongArticleImgHolder(),
      longer: imgService.getLongerArticleImgHolder(),
      circle: imgService.getCircle(),
    };
    this.defaultImg = 'avatar';
    this.element = ele;
  }

  loadImage(imagePath) {
    return Observable
      .create((observer) => {
        let img = new Image();
        img.src = imagePath;
        img.onload = () => {
          observer.next(imagePath);
          observer.complete();
        };
        img.onerror = (err) => {
          observer.error(null);
        };
      });
  }

  setImage(element, imagePath) {
    const isImgNode = element.nodeName.toLowerCase() === 'img';
    if (isImgNode) {
      element.src = imagePath;
    } else {
      element.style.backgroundImage = "url(" + imagePath + ")";
    }
  }

  setLoadedStyle(element) {
    /*let styles = element.className
      .split(' ')
      .filter(function (s) {
        return !!s;
      })
      .filter(function (s) {
        return s !== 'ng-lazyloading';
      });
    styles.push('ng-lazyloaded');
    element.className = styles.join(' ');*/


    let name = element.className;
    const  key = 'ng-lazyloading';
    if (name.indexOf(key) >= 0) {
      name = name.replace(key, 'ng-lazyloaded');
    } else if (name) {
      name += ' ng-lazyloaded';
    } else {
      name = 'ng-lazyloaded';
    }
    element.className = name;
  }

  lazyLoadImage(image, imagePath, defaultImagePath) {
    this.setImage(image, defaultImagePath);

    return this.loadImage(imagePath)
      .do((path) => {
        this.setImage(image, path);
      })
      .catch(() => {
        this.setImage(image, defaultImagePath);
        image.className += ' ng-failed-lazyloaded';
        return Observable.of(1);
      }).do(() => {
        this.setLoadedStyle(image);
      });
  }

  ngAfterContentInit() {
    this.lazyLoadImage(this.element.nativeElement, this.src, this.defaultImg).subscribe(() => {
    });
  }

}

/**
 * @description 点击后弹出下载框
 * @author @chenwh576
 * @date 20170921
 */
@Directive({
  selector: '[downloadApp], downloadApp',
})
export class DownloadAppDirective {
  public _text: string;
  @Input()
  set text(val) {
    this._text = val;
  }

  get text(): string {
    return this._text;
  }

  constructor(private toolsService: ToolsService) {
    this._text = '下载求苗APP，看更多精彩内容!';
  }

  @HostListener('click')
  handleClick() {
    const text = this.text;
    this.toolsService.presentConfirm(text);
  }
}

/**
 * @description 固定元素到顶部
 * @example
 * <seed-content class="spell-detail-inner" #content> //传入content 便于计算content scroll height
 *     <div class="order-nav" #orderNav  fixed-to-roof [content]="content" (onChange)="handleOnChangeEve($event)">
 *     </div>
 * </div>
 * @method 如果固定到顶部后会发出一个onChange(
 * {
            isFixed:boolean,//是否固定在了頂部
            scrollPos:number,//滾動了多少像素
          }
 * )事件，做进一步操作如果没有特殊需求可以不用；
 * @author @chenwh576
 * @date 20171024
 * @params content,onChange
 */
@Directive({
  selector: '[seed-fixed-to-roof],seed-fixed-to-roof',
  host: {class: 'seed-fixed-to-roof'}
})
export class FixedToRoofDirective implements AfterContentInit, OnDestroy {
  private _content: any;
  private scrollListener: any;

  @Input()
  set content(val) {
    this._content = val;
  }

  get content() {
    return this._content;
  }

  @Output() onChange: EventEmitter<Object> = new EventEmitter();

  constructor(
    private ele: ElementRef,
    private renderer: Renderer,
    private events: EventsService
  ) {

  }

  fixedToTop() {
    const node = this.content.content.nativeElement;
     const hostElement = this.ele.nativeElement;
    const  defaultDistance = hostElement.getBoundingClientRect().top;
    // console.warn(defaultDistance)
    this.scrollListener = this.renderer.listen(node,
      'scroll', () => {
        const top = node.scrollTop;
        if (top >= defaultDistance) {
          this.onChange.emit({
            isFixed: false,
            scrollPos: top
          });
          /*if (!hostElement.classList.contains('isFixed')) {
            hostElement.classList.add('isFixed');
          }*/
          hostElement.classList.add('isFixed');
        } else {
          if (top <= defaultDistance && hostElement.classList.contains('isFixed')) {
            this.onChange.emit({
              isFixed: true,
              scrollPos: top
            });
            hostElement.classList.remove('isFixed');
          }
        }

      }
    );
  }

  ngAfterContentInit() {
    let isToTheRoof = false;
    this.events.subscribe('request:finished', () => {
      if (!isToTheRoof) {
        setTimeout(() => {
          this.fixedToTop();
          isToTheRoof = true;
        });
      }
    });
  }


  ngOnDestroy() {
    if (this.scrollListener) {
      this.scrollListener();
    }
  }
}


